package com.kun.dd.aspect;

import com.kun.dd.annotation.DataSource;
import com.kun.dd.datasource.DynamicDataSourceContextHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class DataSourceAspect {

    /**
     * @annotation(com.kun.dd.annotation.DataSource) 拦截方法上的DataSource注解
     * @within(com.kun.dd.annotation.DataSource) 如果类上标有注解，就将类中的方法拦截
     */
    @Pointcut("@annotation(com.kun.dd.annotation.DataSource) || @within(com.kun.dd.annotation.DataSource)")
    public void pc(){};

    @Around("pc()")
    public Object around(ProceedingJoinPoint pjp){
        //优先获取方法上的注解，没有在获取类上的
        DataSource dataSource = getDataSource(pjp);
        if (dataSource != null){
            //获取数据源名称
            String value = dataSource.value();
            DynamicDataSourceContextHolder.setDSType(value);
        }

        try {
            return pjp.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }finally {
            DynamicDataSourceContextHolder.delDSType();
        }
        return null;
    }

    private DataSource getDataSource(ProceedingJoinPoint pjp) {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        //查找方法上的注解
        DataSource annotation = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class);
        if (annotation != null){
            return annotation;
        }
        //方法上没有去类上找
        return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class);
    }
}
